// PGLEngine.cpp : Implementation of CPGLEngine
#include "stdafx.h"
#include "PGLServer.h"
#include "PGLEngine.h"
#include <initguid.h>
#include <asptlb.h>

/////////////////////////////////////////////////////////////////////////////
// CPGLEngine

STDMETHODIMP CPGLEngine::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = 
	{
		&IID_IPGLEngine
	};
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (::InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}


CPGLVectorFPtr CPGLEngine::SafeArrayToCPGLData(SAFEARRAY* sa)
{
	CPGLSafeArray a(sa, false);
	if (FAILED(a.GetLastHRESULT()))
		return CPGLVectorFPtr();

	const size_t n= a.size();
	CPGLVectorFPtr pV(new CPGLVectorF( n ));
	std::vector<float>& v=pV->GetV();
	for (size_t i=0;i<n;++i)
		v[i]=a[i];

	return pV;
}

STDMETHODIMP CPGLEngine::Figure(long* plDlgID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plDlgID=m_script.Figure();
	return S_OK;
}

STDMETHODIMP CPGLEngine::Plot(long lRegionID, SAFEARRAY* saX, SAFEARRAY* saY, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.Plot( lRegionID, SafeArrayToCPGLData(saX), SafeArrayToCPGLData(saY), _bstr_t(bstrFormat) );
	return S_OK;
}


STDMETHODIMP CPGLEngine::PlotY(long lRegionID, double dX0, double dXStep, SAFEARRAY* saY, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.PlotY( lRegionID, (float)dX0, (float)dXStep, SafeArrayToCPGLData(saY), _bstr_t(bstrFormat) );
	return S_OK;
}

STDMETHODIMP CPGLEngine::PlotFcn(long lRegionID, SAFEARRAY* saX, BSTR bstrFcnX, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.PlotFcn( lRegionID, SafeArrayToCPGLData(saX), _bstr_t(bstrFcnX), _bstr_t(bstrFormat) );
	return S_OK;
}

STDMETHODIMP CPGLEngine::PlotFcnY(long lRegionID, long nPoints, double fX0, double fXStep, BSTR bstrFcnX, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.PlotFcnY( lRegionID, nPoints, static_cast<float>(fX0), static_cast<float>(fXStep), _bstr_t(bstrFcnX), _bstr_t(bstrFormat) );
	return S_OK;
}

STDMETHODIMP CPGLEngine::Histogram(long lRegionID, SAFEARRAY* saY, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.Histogram( lRegionID, SafeArrayToCPGLData(saY), _bstr_t(bstrFormat) );
	return S_OK;
}

STDMETHODIMP CPGLEngine::Scatter(long lRegionID, SAFEARRAY* saX, SAFEARRAY* saY, SAFEARRAY* saValues, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.Scatter( lRegionID, SafeArrayToCPGLData(saX), SafeArrayToCPGLData(saY), SafeArrayToCPGLData(saValues), _bstr_t(bstrFormat) );
	return S_OK;
}

STDMETHODIMP CPGLEngine::PlotLOD(long lRegionID, SAFEARRAY* saX, SAFEARRAY* saY, float fCompRatio, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.PlotLOD( lRegionID, SafeArrayToCPGLData(saX), SafeArrayToCPGLData(saY), fCompRatio,_bstr_t(bstrFormat) );
	return S_OK;
}

STDMETHODIMP CPGLEngine::PlotLODY(long lRegionID, double dX0, double dXStep, SAFEARRAY* saY, float fCompRatio, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.PlotLODY( lRegionID, (float)dX0, (float)dXStep, SafeArrayToCPGLData(saY), fCompRatio,_bstr_t(bstrFormat) );
	return S_OK;
}

STDMETHODIMP CPGLEngine::Stock(long lRegionID, double dX0, double dXStep, SAFEARRAY* saOpen, SAFEARRAY* saHigh,SAFEARRAY* saLow,SAFEARRAY* saClose, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.Stock( lRegionID, static_cast<float>(dX0), static_cast<float>(dXStep), SafeArrayToCPGLData(saOpen), SafeArrayToCPGLData(saHigh), SafeArrayToCPGLData(saLow), SafeArrayToCPGLData(saClose), _bstr_t(bstrFormat) );
	
	return S_OK;
}

STDMETHODIMP CPGLEngine::CandleStick(long lRegionID, double dX0, double dXStep, SAFEARRAY* saOpen, SAFEARRAY* saHigh,SAFEARRAY* saLow,SAFEARRAY* saClose, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())
		
		*plObjectID = m_script.CandleStick( lRegionID, static_cast<float>(dX0), static_cast<float>(dXStep), SafeArrayToCPGLData(saOpen), SafeArrayToCPGLData(saHigh), SafeArrayToCPGLData(saLow), SafeArrayToCPGLData(saClose), _bstr_t(bstrFormat) );
	
	return S_OK;
}

STDMETHODIMP CPGLEngine::ErrorBar(long lRegionID, SAFEARRAY* saX, SAFEARRAY* saY,SAFEARRAY* saErrorUp,SAFEARRAY* saErrorDown, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.ErrorBar( lRegionID, SafeArrayToCPGLData(saX), SafeArrayToCPGLData(saY), SafeArrayToCPGLData(saErrorUp), SafeArrayToCPGLData(saErrorDown), _bstr_t(bstrFormat) );
	
	return S_OK;
}

STDMETHODIMP CPGLEngine::ErrorBarY(long lRegionID, double dX0, double dXStep, SAFEARRAY* saY,SAFEARRAY* saErrorUp,SAFEARRAY* saErrorDown, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.ErrorBarY( lRegionID, (float)dX0, (float)dXStep, SafeArrayToCPGLData(saY), SafeArrayToCPGLData(saErrorUp), SafeArrayToCPGLData(saErrorDown), _bstr_t(bstrFormat) );
	
	return S_OK;
}

STDMETHODIMP CPGLEngine::Region(long *plRegionID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plRegionID = m_script.Region();
	return S_OK;
}

STDMETHODIMP CPGLEngine::Title(long lRegionID, BSTR bstrLabel, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID=m_script.Title(lRegionID, _bstr_t(bstrLabel) );
	return S_OK;
}

STDMETHODIMP CPGLEngine::LeftLabel(long lRegionID, BSTR bstrLabel, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID=m_script.LeftLabel(lRegionID, _bstr_t(bstrLabel) );
	return S_OK;
}


STDMETHODIMP CPGLEngine::RightLabel(long lRegionID, BSTR bstrLabel, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID=m_script.RightLabel(lRegionID, _bstr_t(bstrLabel) );
	return S_OK;
}


STDMETHODIMP CPGLEngine::BottomLabel(long lRegionID, BSTR bstrLabel, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID=m_script.BottomLabel(lRegionID, _bstr_t(bstrLabel) );
	return S_OK;
}

STDMETHODIMP CPGLEngine::GetCR(long *plRegionID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plRegionID = m_script.GetCR();
	return S_OK;
}

STDMETHODIMP CPGLEngine::Divide(long lRegionID, long lnRows, long lnCols, long *plRegionID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plRegionID = m_script.Divide( lRegionID, lnRows, lnCols);
	return S_OK;
}

STDMETHODIMP CPGLEngine::GetParent(long lObjectID, long *plParentID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plParentID = m_script.GetParent(lObjectID);

	return S_OK;
}

STDMETHODIMP CPGLEngine::GetHelp(long lObjectID, BSTR *pbstrHelp)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	CString str;
	m_script.GetHelp( lObjectID, str);

	_bstr_t bstr(str);
	*pbstrHelp = bstr.copy();

	return S_OK;
}

STDMETHODIMP CPGLEngine::Get(long lObjectID, BSTR bstrProp, BSTR *pbstrValue)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	CString str;
	m_script.Get(lObjectID, _bstr_t(bstrProp), str);

	_bstr_t bstr(str);
	*pbstrValue = bstr.copy();

	return S_OK;
}

STDMETHODIMP CPGLEngine::Set(long lObjectID, BSTR bstrPropAndValues)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	m_script.Set(lObjectID, _bstr_t( bstrPropAndValues) );

	return S_OK;
}

STDMETHODIMP CPGLEngine::CloseRegion(long lRegionID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	m_script.CloseRegion(lRegionID);

	return S_OK;
}

STDMETHODIMP CPGLEngine::CloseFigure(long lFigID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	m_script.CloseFigure(lFigID);

	return S_OK;
}

STDMETHODIMP CPGLEngine::CloseAllFigures()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	m_script.CloseAllFigures();

	return S_OK;
}


STDMETHODIMP CPGLEngine::CloseAllRegions()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	m_script.CloseAllRegions();

	return S_OK;
}

STDMETHODIMP CPGLEngine::GetChild(long lParentID, long lIndex, long *plChildID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plChildID=m_script.GetChild( lParentID, lIndex-1);

	return S_OK;
}
 
STDMETHODIMP CPGLEngine::GetObject(long lRegionID, long lIndex, long* plObjectID)
{
 	AFX_MANAGE_STATE(AfxGetStaticModuleState())
 
	*plObjectID=m_script.GetObject( lRegionID, lIndex-1);
 
 	return S_OK;
}

STDMETHODIMP CPGLEngine::GetChildrenSize(long lRegionID, long *plChildrenSize)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plChildrenSize = m_script.GetChildrenSize( lRegionID );

	return S_OK;
}

STDMETHODIMP CPGLEngine::GetObjectsSize(long lRegionID, long *plObjectsSize)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectsSize = m_script.GetObjectsSize( lRegionID );

	return S_OK;
}

STDMETHODIMP CPGLEngine::SetCR(long lRegionID, VARIANT_BOOL* pbSuccess)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*pbSuccess = (m_script.SetCR(lRegionID)) ? VARIANT_TRUE : VARIANT_FALSE;

	return S_OK;
}

STDMETHODIMP CPGLEngine::SaveXML(long lRegionID, BSTR bstrFileName, VARIANT_BOOL bZipping, VARIANT_BOOL *pbSuccess)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*pbSuccess = (m_script.SaveToXML( lRegionID, _bstr_t(bstrFileName), bZipping != VARIANT_FALSE )) ? VARIANT_TRUE : VARIANT_FALSE;
	
	return S_OK;
}

STDMETHODIMP CPGLEngine::LoadXML(long lRegionID, BSTR bstrFileName, VARIANT_BOOL *pbSuccess)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*pbSuccess = (m_script.LoadFromXML( lRegionID, _bstr_t(bstrFileName) )) ? VARIANT_TRUE : VARIANT_FALSE;

	return S_OK;
}

STDMETHODIMP CPGLEngine::RenderToFile(long lRegionID, BSTR bstrFileName, BSTR bstrFormat, VARIANT_BOOL *pbSuccess)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*pbSuccess= (m_script.RenderToFile( lRegionID, _bstr_t(bstrFileName), _bstr_t(bstrFormat))) ? VARIANT_TRUE : VARIANT_FALSE;

	return S_OK;
}

STDMETHODIMP CPGLEngine::Legend(long lRegionID, long *lLegendID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*lLegendID = m_script.Legend( lRegionID);

	return S_OK;
}

STDMETHODIMP CPGLEngine::OutOfChild()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	m_script.OutOfChild();

	return S_OK;
}

STDMETHODIMP CPGLEngine::RenderToStream(long lRegionID, IUnknown* pIStreamObj, BSTR bstrFormat, VARIANT_BOOL* pbSuccess)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	if (!pIStreamObj)
	{
		ATLTRACE( "CPGLEngine::RenderToStream Error: pIStreamObj is Null");
		return S_FALSE;
	}

	ATL::CComQIPtr< IStream, &IID_IStream> pStream( pIStreamObj );
	if (!pStream)
	{
		ATLTRACE( "CPGLEngine::RenderToStream Error: IDispatch does not implement IStream interface");
		return S_FALSE;
	}

	*pbSuccess=m_script.RenderToStream( lRegionID, pStream, _bstr_t(bstrFormat) );

	return S_OK;
}

STDMETHODIMP CPGLEngine::RenderToResponse(long lRegionID, IUnknown* pIResponseObj, BSTR bstrFormat, VARIANT_BOOL* pbSuccess)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())
	USES_CONVERSION;

	if (!pIResponseObj)
	{
		ATLTRACE( "CPGLEngine::RenderToResponse Error: pUnknwown is Null");
		return S_FALSE;
	}

	ATL::CComQIPtr< IResponse, &IID_IResponse > pIResponse( pIResponseObj );
	if (!pIResponseObj)
      return S_FALSE;


	algotools::CMemStream memStream;
	if (!memStream.IsValid())
		return S_FALSE;

	*pbSuccess=m_script.RenderToStream( lRegionID, memStream.ToStream(), _bstr_t(bstrFormat) );

	// formulate a proper header
	pIResponse->put_Buffer(true);
	pIResponse->put_ContentType(T2BSTR(_T("image/png")));
	pIResponse->BinaryWrite( memStream.ToVariant() );
	pIResponse->Flush();

	return TRUE;
}

STDMETHODIMP CPGLEngine::AutoZoom(BSTR bstrState)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	m_script.AutoZoom( _bstr_t( bstrState ));

	return S_OK;
}

STDMETHODIMP CPGLEngine::Grid(long lRegionID, BSTR bstrState, long* plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID=m_script.Grid( lRegionID, _bstr_t( bstrState ));

	return S_OK;
}


STDMETHODIMP CPGLEngine::PlotHor(long lRegionID, double dY, BSTR bstrFlags, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	
	*plObjectID = m_script.PlotHor( lRegionID, static_cast<float>(dY), _bstr_t( bstrFlags ) );

	return S_OK;
}

STDMETHODIMP CPGLEngine::PlotVer(long lRegionID, double dX, BSTR bstrFlags, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.PlotVer( lRegionID, static_cast<float>(dX), _bstr_t( bstrFlags ) );

	return S_OK;
}

STDMETHODIMP CPGLEngine::Image(long lRegionID, BSTR bstrFileName, BSTR bstrFormat, long *plObjectID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plObjectID = m_script.Image( lRegionID, _bstr_t( bstrFileName), _bstr_t( bstrFormat ) );

	return S_OK;
}

STDMETHODIMP CPGLEngine::Layout(long lRegionID, BSTR bstrLayout, long *plRegionID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*plRegionID = m_script.Layout(lRegionID, _bstr_t(bstrLayout));
		
	return S_OK;
}

STDMETHODIMP CPGLEngine::DoModalRegion(long lRegionID, int *iResult)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*iResult = m_script.DoModalRegion(lRegionID);
		
	return S_OK;
}

STDMETHODIMP CPGLEngine::LoadCSVFile(long lRegionID, BSTR bstrFileName, VARIANT_BOOL *pbResult)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	*pbResult = m_script.LoadCSVFile(lRegionID,_bstr_t(bstrFileName));
		
	return S_OK;
}
